#!/bin/bash

set -o errexit

test_dir=$(realpath $(dirname $0))
. ${test_dir}/../functions

set_debug

get_mgmnt_service_list() {
	local api_key=$1
	local endpoint=$2
	local namespace=$3

	curl -s -k -H "Authorization: Bearer ${api_key}" -X POST "https://$endpoint/v1/management/Service/List" \
		| jq 'walk(if type=="object" then with_entries(select(.key | test("service_id|node_id|agent_id|created_at|updated_at") | not)) else . end)' \
		| jq 'walk(if type == "array" then sort_by(.agent_type) else . end)' \
			>${tmp_dir}/active_pmm_agents.json

	# Pmm server is serving one namespace only, so stripping the namespace name out
	$sed -i 's/'${namespace}'-//g' ${tmp_dir}/active_pmm_agents.json
	cat ${tmp_dir}/active_pmm_agents.json | jq '.services | sort_by(.node_name)' >${tmp_dir}/active_pmm_agents_sorted.json

	echo "${tmp_dir}/active_pmm_agents_sorted.json"
}

get_node_id_from_pmm() {
	local -a nodeList=()
	for instance in $(kubectl_bin get pods --no-headers -l app.kubernetes.io/component=pxc --output=custom-columns='NAME:.metadata.name'); do
		nodeList+=($(kubectl_bin exec -n "$namespace" $instance -c pmm-client -- pmm-admin status --json | jq -r '.pmm_agent_status.node_id'))
	done

	echo "${nodeList[@]}"
}

does_node_id_exists() {
	local -a nodeList=("$@")
	local -a nodeList_from_pmm=()
	for node_id in "${nodeList[@]}"; do
		nodeList_from_pmm+=($(kubectl_bin exec -n "${namespace}" monitoring-0 -- pmm-admin --server-url=https://admin:admin@$(get_service_ip monitoring-service)/ --server-insecure-tls inventory list nodes --node-type=CONTAINER_NODE | grep $node_id | awk '{print $4}'))
	done

	echo "${nodeList_from_pmm[@]}"
}

cluster="monitoring"

create_infra $namespace
deploy_helm $namespace

desc 'install PMM Server'
deploy_pmm_server
kubectl_bin wait --for=condition=Ready pod/${cluster}-0 --timeout=120s
until kubectl_bin exec monitoring-0 -- bash -c "ls -l /proc/*/exe 2>/dev/null| grep postgres >/dev/null"; do
	echo "Retry $retry"
	sleep 5
	let retry+=1
	if [ $retry -ge 20 ]; then
		echo "Max retry count $retry reached. Pmm-server can't start"
		exit 1
	fi
done
ADMIN_PASSWORD=$(kubectl_bin exec monitoring-0 -- bash -c "printenv | grep ADMIN_PASSWORD | cut -d '=' -f2")
sleep 5
kubectl_bin exec monitoring-0 -- bash -c "grafana-cli --homepath=/usr/share/grafana --config=/etc/grafana/grafana.ini admin reset-admin-password $ADMIN_PASSWORD"

desc 'create PXC cluster'
spinup_pxc "$cluster" "$test_dir/conf/$cluster.yml" 3 120 "$test_dir/conf/secrets.yaml"

desc 'add PMM API key to secret'
API_KEY=$(curl --insecure -X POST -H "Content-Type: application/json" -d '{"name":"operator", "role": "Admin"}' "https://admin:$ADMIN_PASSWORD@$(get_service_endpoint monitoring-service)/graph/api/auth/keys" | jq .key)
kubectl_bin patch secret my-cluster-secrets --type merge --patch '{"stringData": {"pmmserverkey": '"$API_KEY"'}}'

wait_for_generation "sts/$cluster-pxc" 2
wait_for_generation "sts/$cluster-haproxy" 2
sleep 10
kubectl wait pod -l 'app.kubernetes.io/managed-by=percona-xtradb-cluster-operator' --for=condition=ready --timeout=600s
wait_cluster_consistency ${cluster} 3 2

compare_kubectl statefulset/$cluster-pxc "-no-prefix"
compare_kubectl statefulset/$cluster-haproxy "-no-prefix"

desc 'apply my-env-var-secrets to add PMM_PREFIX'
kubectl_bin apply -f "$test_dir/conf/envsecrets.yaml"

wait_for_generation "sts/$cluster-pxc" 3
wait_for_generation "sts/$cluster-haproxy" 3

desc 'add new PMM API key to secret'
API_KEY_NEW=$(curl --insecure -X POST -H "Content-Type: application/json" -d '{"name":"operator-new", "role": "Admin"}' "https://admin:$ADMIN_PASSWORD@$(get_service_endpoint monitoring-service)/graph/api/auth/keys" | jq .key)
kubectl_bin patch secret my-cluster-secrets --type merge --patch '{"stringData": {"pmmserverkey": '"$API_KEY_NEW"'}}'

desc 'delete old PMM key'
ID_API_KEY_OLD=$(curl --insecure -X GET "https://admin:$ADMIN_PASSWORD@$(get_service_endpoint monitoring-service)/graph/api/auth/keys" | jq '.[] | select( .name == "operator").id')
curl --insecure -X DELETE "https://admin:$ADMIN_PASSWORD@$(get_service_endpoint monitoring-service)/graph/api/auth/keys/$ID_API_KEY_OLD"

wait_for_generation "sts/$cluster-pxc" 4
wait_for_generation "sts/$cluster-haproxy" 4

sleep 10
kubectl wait pod -l 'app.kubernetes.io/managed-by=percona-xtradb-cluster-operator' --for=condition=ready --timeout=600s

desc 'check if pmm-client container enabled'
compare_kubectl statefulset/$cluster-pxc
compare_kubectl statefulset/$cluster-haproxy

desc 'verify clients agents statuses'
# wait for proper agents statuses
sleep 300
API_KEY=$(getSecretData "my-cluster-secrets" "pmmserverkey")
diff -u ${test_dir}/compare/agents-list.json $(get_mgmnt_service_list ${API_KEY} $(get_service_endpoint monitoring-service) ${namespace})

desc 'check mysql metrics'
get_metric_values node_boot_time_seconds pxc-prefix-$namespace-$cluster-pxc-0 admin:admin
get_metric_values mysql_global_status_uptime pxc-prefix-$namespace-$cluster-pxc-0 admin:admin

desc 'check haproxy metrics'
get_metric_values haproxy_backend_status pxc-prefix-$namespace-$cluster-haproxy-0 admin:admin
get_metric_values haproxy_backend_active_servers pxc-prefix-$namespace-$cluster-haproxy-0 admin:admin

desc 'check QAN data'
get_qan20_values $cluster-pxc-0 admin:admin

nodeList=($(get_node_id_from_pmm))
nodeList_from_pmm=($(does_node_id_exists "${nodeList[@]}"))
for node_id in "${nodeList_from_pmm[@]}"; do
	if [ -z "$node_id" ]; then
		echo "Can't get $node_id node_id from PMM server"
		exit 1
	fi
done

kubectl_bin patch pxc ${cluster} --type json -p='[{"op":"add","path":"/spec/pause","value":true}]'
wait_for_delete "pod/${cluster}-pxc-0"

does_node_id_exists_in_pmm=($(does_node_id_exists "${nodeList[@]}"))
for instance in "${does_node_id_exists_in_pmm[@]}"; do
	if [ -n "$instance" ]; then
		echo "The $instance pod was not deleted from server inventory"
		exit 1
	fi
done

if [[ -n ${OPENSHIFT} ]]; then
	oc adm policy remove-scc-from-user privileged -z pmm-server
	if [ -n "$OPERATOR_NS" ]; then
		oc delete clusterrolebinding pmm-pxc-operator-cluster-wide
	else
		oc delete rolebinding pmm-pxc-operator-namespace-only
	fi
fi

# Temporarily skipping this check
# desc 'check for passwords leak'
# check_passwords_leak

helm uninstall monitoring
destroy $namespace
desc "test passed"
